/*global pi */

// 注册底层函数时候，用到的参数和返回值类型
pi.mod.define('pi.vcall', function (pi) {
	"use strict";

	var module = {};

	module.TYPE_INT = 2; // 32位整数
	module.TYPE_UINT = 3; // 32位无符号整数
	module.TYPE_BOOL = 4; // 布尔型，按js本身规则处理
	module.TYPE_BYTE = 5; // 8位整数
	module.TYPE_UBYTE = 6; // 8位无符号整数
	module.TYPE_SHORT = 7; // 16位整数
	module.TYPE_USHORT = 8; // 16位无符号整数
	module.TYPE_LONG = 9; // 64位整数
	module.TYPE_ULONG = 10; // 64位无符号整数
	module.TYPE_FLOAT = 11; // 32位浮点数，不能作为返回值
	module.TYPE_DOUBLE = 12; // 64位浮点数
	module.TYPE_STRING = 13; // Unicode编码字符串，这是javascript原生字符串
	module.TYPE_ANSI_STRING = 14; // ANSI本地编码字符串
	module.TYPE_UTF8_STRING = 15; // UTF8字符串
	module.TYPE_CODING_STRING = 16; // 目前没有实现，等需求用到再实现
	module.TYPE_OBJECT = 17; // js对象
	module.TYPE_POINTER = 18; // ArrayBuffer以及对应的Uint32Array等结构的首地址，不能用作返回值
	module.TYPE_BUFFER = 19; // ArrayBuffer以及对应的Uint32Array等结构的数据本身，不能用作返回值
	module.TYPE_VA = 20; // 可变参数，必须是最后一个参数类型，不能用作返回值
	module.TYPE_VOID = 21; // 代表无返回值，不能用作参数类型
	/** 快速注册 vcall，比如：
		vc_tb = [
			["fun_a", pi.vcall.TYPE_VOID, [pi.vcall.TYPE_INT, pi.vcall.TYPE_INT], "aFun"],
			["fun_b", pi.vcall.TYPE_INT, [pi.vcall.TYPE_INT], "bFun"]
		];
		makeVCall("dumb.dll", module, vc_tb);
		将注册两个 js 函数，并附加到 vc_tb 对象上，其中：
			vc_tb.fun_a 将调用 dumb.dll 中名为 fun_a 的 c 函数，有两个 int 参数，无返回值，如果aFun不为空，则module.aFun = vc_tb.fun_a, 否则module.fun_a = vc_tb.fun_a;
			vc_tb.fun_b 将调用 dumb.dll 中名为 fun_b 的 c 函数，有一个 int 参数，返回一个 int，如果bFun不为空，则module.bFun = vc_tb.fun_b, 否则module.fun_b = vc_tb.fun_b;
	*/
	module.makeVCall = function (dllPath, mod, vc_tb) {
		var i = 0,
			help_fun = function (n) {
				return function () {
					var h = vc_tb[vc_tb[n][0] + "_C$Function$Handle"],
						params = Array.prototype.slice.call(arguments);

					if (h === undefined) {
						h = pi.vcall.register(dllPath, vc_tb[n][0], vc_tb[n][1], vc_tb[n][2]);
						vc_tb[vc_tb[n][0] + "_C$Function$Handle"] = h;
					}
					params.unshift(h);
					return pi.vcall.invoke.apply(undefined, params);
				};
			};

		for (i = 0; i < vc_tb.length; i++) {
			vc_tb[vc_tb[i][0]] = help_fun(i);
			if (vc_tb[i][3]) {
				mod[vc_tb[i][3]] = vc_tb[vc_tb[i][0]];
			}
			else {
				mod[vc_tb[i][0]] = vc_tb[vc_tb[i][0]];
			}
		}
	};

	return module;
});